import { stringify } from 'qs'
import { contentType, messageName, statusName, successCode, timeout } from '/@lib/config'
import router from '/@/router'
import { isArray } from '/@lib/utils/validate'
import { addErrorLog, needErrorLog } from '/@lib/plugins/errorLog'
import axios, { AxiosError, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'
import { ModalUtil } from '/@lib/utils/modal.ts'
import { useAuthStore } from '/@/store/modules/auth.ts'
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus'
import { LoadingInstance } from 'element-plus/es/components/loading/src/loading'
import FileSaver from 'file-saver'
import { blobValidate, tansParams } from './util.ts'
import { CODE_MESSAGE } from './CodeMessage.ts'

// 操作正常Code数组
const codeVerificationArray = isArray(successCode) ? [...successCode] : [...[successCode]]

/**
 * axios响应拦截器
 * @param config {any} 请求配置
 * @param data {any} response数据
 * @param status {any} HTTP status
 * @param statusText {any} HTTP status text
 * @returns {Promise<*|*>}
 */
const handleData = async ({ data, status, statusText }: { config: any; data: any; status: any; statusText: any }) => {
  // const { resetAll } = useAuthStore()
  // if (loadingInstance) loadingInstance.close();

  // 二进制数据则直接返回
  // if (data.request.responseType === 'blob' || data.request.responseType === 'arraybuffer') {
  //   return data.data;
  // }

  // 若data.code存在，覆盖默认code
  let code = data && data[statusName] ? data[statusName] : status
  // 若code属于操作正常code，则status修改为200
  if (codeVerificationArray.indexOf(data[statusName]) + 1) code = 200
  switch (code) {
    case 200:
      // 业务层级错误处理，以下是假定restful有一套统一输出格式(指不管成功与否都有相应的数据格式)情况下进行处理
      // 例如响应内容：
      // 错误内容：{ code: 1, msg: '非法参数' }
      // 正确内容：{ code: 200, data: {  }, msg: '操作正常' }
      // return data
      return data
    case 401:
      // resetAll().then(() => {
      //   router.push({ path: '/login', replace: true }).then(() => {
      //   })
      // })
      handleAuthorized()
      break
    case 402:
    // return await tryRefreshToken(config);
    case 403:
      router.push({ path: '/403' }).then(() => {
      })
      break
    case 30000:
      break
  }
  // 异常处理
  // 若data.msg存在，覆盖默认提醒消息
  const errMsg = `${data && data[messageName] ? data[messageName] : CODE_MESSAGE[code] ? CODE_MESSAGE[code] : statusText}`
  // 是否显示高亮错误(与errorHandler钩子触发逻辑一致)
  // gp.$baseMessage(errMsg, 'error', 'hey');
  // ModalUtil.msgError(errMsg)
  ModalUtil.notifyError(errMsg)
  if (needErrorLog()) addErrorLog({ message: errMsg, stack: data, isRequest: true })
  return Promise.reject(data)
}

const handleAuthorized = () => {
  ElMessageBox.confirm('登录超时，请重新登录', '提示', {
    showCancelButton: false,
    closeOnClickModal: false,
    showClose: false,
    confirmButtonText: '重新登录',
    type: 'warning'
  }).then(() => {
    useAuthStore()
      .logout()
      .then(() => {
        location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'
      })
    // return Promise.reject('登录超时，请重新登录')
  })
}

// axios.defaults.headers['clientId'] = import.meta.env.VITE_APP_CLIENT_ID

/**
 * @description axios初始化
 */
const instance = axios.create({
  baseURL: `${import.meta.env.VITE_APP_BASE_URL}`,
  timeout,
  headers: {
    'Content-Type': contentType,
    ClientId: `${import.meta.env.VITE_APP_CLIENT_ID}`
  }
})

/**
 * @description axios请求拦截器
 */
instance.interceptors.request.use(
  (config: InternalAxiosRequestConfig) => {
    // const userStore = useUserStore()
    const authStore = useAuthStore()
    const { token } = authStore
    // 不规范写法 可根据setting.config.js tokenName配置随意自定义headers
    // if (token) config.headers[tokenName] = token

    // 规范写法 不可随意自定义
    if (token) config.headers['Authorization'] = `Bearer ${token}`

    // get请求映射params参数
    if (config.method === 'get' && config.params) {
      let url = config.url + '?' + tansParams(config.params)
      url = url.slice(0, -1)
      config.params = {}
      config.url = url
    }

    if (config.data && config.headers['Content-Type'] === 'application/x-www-form-urlencoded;charset=UTF-8')
      config.data = stringify(config.data)

    // if (debounce.some((item: string) => config.url?.includes(item))) loadingInstance = gp.$baseLoading();

    return config
  },
  (error) => {
    console.log('请求拦截器错误', error)
    return Promise.reject(error)
  }
)

/**
 * @description axios响应拦截器
 */
instance.interceptors.response.use(
  (response) => handleData(response),
  (error: AxiosError) => {
    const { response } = error
    console.log('响应拦截器错误', error)
    if (response === undefined) {
      // return {};
      ModalUtil.msgError(
        '连接后台接口失败，可能由以下原因造成：' +
        '后端不支持跨域CORS、接口地址不存在、请求超时等，请联系管理员排查后端接口问题 '
      )
      return Promise.reject(error)
    } else {
      return handleData(response)
    }
  }
)

const request = <T = any>(config: AxiosRequestConfig): Promise<T> => {
  return new Promise((resolve, reject) => {
    instance
      .request<T>(config)
      .then((res: AxiosResponse) => resolve(res.data))
      .catch((err: { message: string }) => reject(err))
  })
}

const get = <T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<T> => {
  return request({
    method: 'get',
    url,
    params,
    ...config
  })
}

const postParams = <T = any>(url: string, params: object, config?: AxiosRequestConfig): Promise<T> => {
  return request({
    method: 'post',
    url,
    params,
    ...config
  })
}
const post = <T = any>(url: string, data?: object, config?: AxiosRequestConfig): Promise<T> => {
  return request({
    method: 'post',
    url,
    data,
    ...config
  })
}

// 通用下载方法
let downloadLoadingInstance: LoadingInstance
const download = (url: string, params: any, fileName: string) => {
  downloadLoadingInstance = ElLoading.service({ text: '正在下载数据，请稍候', background: 'rgba(0, 0, 0, 0.7)' })
  // prettier-ignore
  return instance.post(url, params, {
    transformRequest: [
      (params: any) => {
        return tansParams(params)
      }
    ],
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    responseType: 'blob'
  }).then(async (resp: any) => {
    const isLogin = blobValidate(resp)
    if (isLogin) {
      const blob = new Blob([resp])
      FileSaver.saveAs(blob, fileName)
    } else {
      // const resText = await resp.data.text()
      // const rspObj = JSON.parse(resText)
      // const errMsg = `${data && data[messageName] ? data[messageName] : CODE_MESSAGE[code] ? CODE_MESSAGE[code] : statusText}`

      // const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
      // ElMessage.error(errMsg)
    }
    downloadLoadingInstance.close()
  }).catch((r: any) => {
    console.error(r)
    ElMessage.error('下载文件出现错误，请联系管理员！')
    downloadLoadingInstance.close()
  })
}

// export default instance

export default { request, get, post, postParams, download }
